use super::super::ggg::*;
use super::*;

#[derive(Debug, Clone)]
pub struct Table<'a> {
	pub major_version: u16, // Major version of the JSTF table, = 1.
	pub minor_version: u16, // Minor version of the JSTF table, = 0.
	// uint16 jstfScriptCount // Number of JstfScriptRecords in this table.
	// JstfScriptRecord jstfScriptRecords[jstfScriptCount] // Array of JstfScriptRecords, in alphabetical order by jstfScriptTag.
	pub records: JstfScriptList<'a>,
}
impl<'a> Table<'a> {
	pub fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			major_version: s.read()?,
			minor_version: s.read()?,
			records: JstfScriptList::parse(s.tail()?)?,
		})
	}
}

pub type JstfScriptList<'a> = RecordList<'a, JstfScript<'a>>;

#[derive(Debug, Clone)]
pub struct JstfScript<'a> {
	pub tag: Tag,
	// Offset16	extenderGlyphOffset	// Offset to ExtenderGlyph table, from beginning of JstfScript table (may be NULL).
	pub extender_glyph: Option<ExtenderGlyph<'a>>,
	// Offset16	defJstfLangSysOffset	// Offset to default JstfLangSys table, from beginning of JstfScript table (may be NULL).
	pub default: Option<JstfLangSys<'a>>,
	// uint16	jstfLangSysCount	// Number of JstfLangSysRecords in this table- may be zero (0).
	// JstfLangSysRecord	jstfLangSysRecords[jstfLangSysCount]	// Array of JstfLangSysRecords, in alphabetical order by JstfLangSysTag.
	pub record: JstfLangSysList<'a>,
}
impl<'a> RecordListItem<'a> for JstfScript<'a> {
	fn parse(tag: Tag, data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			tag,
			extender_glyph: s.parse_at_offset16(data),
			default: s
				.read_at_offset16(data)
				.and_then(|d| JstfLangSys::parse(Tag::from_bytes(b"dflt"), d)),
			record: JstfLangSysList::parse(s.tail()?)?,
		})
	}
}

pub type ExtenderGlyph<'a> = LazyArray16<'a, GlyphId>;

pub type JstfLangSysList<'a> = RecordList<'a, JstfLangSys<'a>>;

#[derive(Debug, Clone)]
pub struct JstfLangSys<'a> {
	pub tag: Tag,
	// uint16	jstfPriorityCount	Number of JstfPriority tables.
	// Offset16	jstfPriorityOffsets[jstfPriorityCount]	Array of offsets to JstfPriority tables, from beginning of JstfLangSys table, in priority order.
	pub priority: LazyOffsetArray16<'a, JstfPriority<'a>>,
}
impl<'a> RecordListItem<'a> for JstfLangSys<'a> {
	fn parse(tag: Tag, data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			tag,
			priority: { LazyOffsetArray16::new(data, s.parse_array16()?) },
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct JstfPriority<'a> {
	// Offset16	gsubShrinkageEnableOffset	Offset to GSUB shrinkage-enable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gsub_shrinkage_enable: Option<JstfModList<'a>>,
	// Offset16	gsubShrinkageDisableOffset	Offset to GSUB shrinkage-disable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gsub_shrinkage_disable: Option<JstfModList<'a>>,
	// Offset16	gposShrinkageEnableOffset	Offset to GPOS shrinkage-enable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gpos_shrinkage_enable: Option<JstfModList<'a>>,
	// Offset16	gposShrinkageDisableOffset	Offset to GPOS shrinkage-disable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gpos_shrinkage_disable: Option<JstfModList<'a>>,
	// Offset16	shrinkageJstfMaxOffset	Offset to shrinkage JstfMax table, from beginning of JstfPriority table (may be NULL).
	pub shrinkage_jstf_max: Option<JstfMax<'a>>,
	// Offset16	gsubExtensionEnableOffset	Offset to GSUB extension-enable JstfModList table, from beginnning of JstfPriority table (may be NULL).
	pub gsub_extension_enable: Option<JstfModList<'a>>,
	// Offset16	gsubExtensionDisableOffset	Offset to GSUB extension-disable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gsub_extension_disable: Option<JstfModList<'a>>,
	// Offset16	gposExtensionEnableOffset	Offset to GPOS extension-enable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gpos_extension_enable: Option<JstfModList<'a>>,
	// Offset16	gposExtensionDisableOffset	Offset to GPOS extension-disable JstfModList table, from beginning of JstfPriority table (may be NULL).
	pub gpos_extension_disable: Option<JstfModList<'a>>,
	// Offset16	extensionJstfMaxOffset	Offset to extension JstfMax table, from beginning of JstfPriority table (may be NULL).
	pub extension_jstf_max: Option<JstfMax<'a>>,
}
impl<'a> FromSlice<'a> for JstfPriority<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			gsub_shrinkage_enable: s.parse_at_offset16(data),
			gsub_shrinkage_disable: s.parse_at_offset16(data),
			gpos_shrinkage_enable: s.parse_at_offset16(data),
			gpos_shrinkage_disable: s.parse_at_offset16(data),
			shrinkage_jstf_max: s.parse_at_offset16(data),
			gsub_extension_enable: s.parse_at_offset16(data),
			gsub_extension_disable: s.parse_at_offset16(data),
			gpos_extension_enable: s.parse_at_offset16(data),
			gpos_extension_disable: s.parse_at_offset16(data),
			extension_jstf_max: s.parse_at_offset16(data),
		})
	}
}

pub type JstfModList<'a> = LazyArray16<'a, u16>;

pub type JstfMax<'a> = LookupList<'a, super::gpos::Subtable<'a>>;
